﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;
using System.IO;

namespace Vit.Report.XmlWebReport
{
    public class RectanglePosition
    {
        private string topLeftPosition;
        private string bottomRightPosition;
        private int topIndex;
        private int bottomIndex;
        private char leftIndex;
        private char rightIndex;
        private SizeF size;
        private SizeF cellSize;

        public RectanglePosition(string topLeftPosition, string bottomRightPosition)
        {
            this.TopLeftPosition = topLeftPosition;
            this.BottomRightPosition = bottomRightPosition;
            LineHeight = 1.0;
            LetterSpacing = 0;
            Editable = false;
            this.Visible = true;
        }

        public void Crop(RectanglePosition cropRect, out RectanglePosition rightRect, out RectanglePosition bottomRect)
        {
            rightRect = null;
            bottomRect = null;

            if (this.RightIndex <= cropRect.LeftIndex && this.BottomIndex <= cropRect.TopIndex)
                return;
            if (this.LeftIndex >= cropRect.LeftIndex && this.RightIndex <= cropRect.RightIndex && this.TopIndex >= cropRect.TopIndex && this.BottomIndex <= cropRect.BottomIndex)
                return;

            string topLeftPosition;
            string bottomRightPosition;
            int xshift = 0;

            if (cropRect.RightIndex < this.RightIndex)
            {
                topLeftPosition = string.Format("A{0}", this.TopIndex);

                if (this.BottomIndex > cropRect.BottomIndex)
                {
                    xshift = this.RightIndex - cropRect.RightIndex - 1;
                    if (xshift < 0)
                        xshift = 0;
                    bottomRightPosition = string.Format("{0}{1}",
                        (char)('A' + xshift), cropRect.BottomIndex);
                    rightRect = new RectanglePosition(topLeftPosition, bottomRightPosition);

                    topLeftPosition = string.Format("{0}{1}",
                        this.LeftIndex, 1);
                    bottomRightPosition = string.Format("{0}{1}",
                        this.RightIndex, this.BottomIndex - cropRect.BottomIndex);
                    bottomRect = new RectanglePosition(topLeftPosition, bottomRightPosition);

                    this.BottomRightPosition = string.Format("{0}{1}",
                        cropRect.RightIndex, cropRect.BottomIndex);
                }
                else
                {
                    xshift = this.RightIndex - cropRect.RightIndex - 1;
                    if (xshift < 0)
                        xshift = 0;
                    bottomRightPosition = string.Format("{0}{1}",
                        (char)('A' + xshift), this.BottomIndex);
                    rightRect = new RectanglePosition(topLeftPosition, bottomRightPosition);

                    this.BottomRightPosition = string.Format("{0}{1}",
                        cropRect.RightIndex, this.BottomIndex);
                }
            }
            else
            {
                if(cropRect.BottomIndex > this.BottomIndex)
                    bottomRightPosition = string.Format("{0}{1}",
                    this.RightIndex, this.BottomIndex);
                else
                    bottomRightPosition = string.Format("{0}{1}",
                        this.RightIndex, this.BottomIndex - cropRect.BottomIndex);
                if (this.TopIndex > cropRect.BottomIndex)
                {
                    topLeftPosition = string.Format("{0}{1}",
                        this.LeftIndex, this.TopIndex - cropRect.BottomIndex);

                    this.Visible = false;
                }
                else
                {
                    topLeftPosition = string.Format("{0}{1}",
                        this.LeftIndex, 1);
                    this.BottomRightPosition = string.Format("{0}{1}",
                        this.RightIndex, cropRect.BottomIndex);
                }
                bottomRect = new RectanglePosition(topLeftPosition, bottomRightPosition);

            }

        }

        public void Move(int xOffset, int yOffset)
        {
            TopLeftPosition = string.Format("{0}{1}",
                (char)(LeftIndex + xOffset), TopIndex + yOffset);
            BottomRightPosition = string.Format("{0}{1}",
                (char)(RightIndex + xOffset), BottomIndex + yOffset);
        }

        public void Offset(float x, float y)
        {
            OffsetPoint = new PointF(x, y);
        }

        public void Append(float width, float height)
        {
            AppendSize = new SizeF(width, height);
        }

        public void AppendTo(int right, int bottom)
        {
            BottomRightPosition = string.Format("{0}{1}",
                (char)(RightIndex + right), BottomIndex + bottom);
        }

        public void Render(TextWriter writer, string id, string innerContent, string cssClass, string style, int zIndex, Font font, Page page)
        {
            if (this.Visible == false)
                return;

            innerContent = ReportHelper.ReplaceTokens(page, innerContent);

            RectangleF rect = ReportHelper.GetRectangle(page, this);
            if (OffsetPoint != PointF.Empty)
            {
                rect.X += OffsetPoint.X;
                rect.Y += OffsetPoint.Y;
            }
            if (AppendSize != SizeF.Empty)
            {
                rect.Width += AppendSize.Width;
                rect.Height += AppendSize.Height;
            }

            SizeF textSize = ReportHelper.GetFontSize(font, innerContent, LineHeight);
            bool isMultiline = rect.Width < textSize.Width || rect.Height < textSize.Height;

            if (isMultiline)
                cssClass += " multiline";

            page.Renderer.RenderCell(writer, page, this, rect, id, innerContent, cssClass, style, zIndex, font);
        }

        public RectanglePosition Clone()
        {
            RectanglePosition rect = new RectanglePosition(this.TopLeftPosition, this.BottomRightPosition);
            rect.LineHeight = this.LineHeight;
            return rect;
        }

        public string TopLeftPosition
        {
            get { return topLeftPosition; }
            set
            {
                topLeftPosition = value;
                ReportHelper.TranslateCellIndex(topLeftPosition, out leftIndex, out topIndex);
                size = new SizeF { Width = cellSize.Width * XSpan, Height = cellSize.Height * YSpan };
            }
        }

        public string BottomRightPosition
        {
            get { return bottomRightPosition; }
            set
            {
                bottomRightPosition = value;
                ReportHelper.TranslateCellIndex(bottomRightPosition, out rightIndex, out bottomIndex);
                size = new SizeF { Width = cellSize.Width * XSpan, Height = cellSize.Height * YSpan }; 
            }
        }

        public int TopIndex { get { return topIndex; } }
        public char LeftIndex { get { return leftIndex; } }
        public int BottomIndex { get { return bottomIndex; } }
        public char RightIndex { get { return rightIndex; } }
        public int XSpan
        {
            get { return rightIndex - leftIndex + 1; }
        }
        public int YSpan
        {
            get { return bottomIndex - topIndex + 1; }
        }
        public PointF OffsetPoint { get; set; }
        public SizeF AppendSize { get; set; }
        public bool Visible { get; set; }
        public double LineHeight { get; set; }
        public double LetterSpacing { get; set; }
        public bool Editable { get; set; }
    }
}
